package com.example.day5;


/**
 * 变长数组
 * @author zjianfa
 */
public class List implements CommonCollection, ListInterface {
    /** 常量 */
    private static final int DEFAULT_CAPACITY = 16;
    /** 扩容因子 */
    private static final int SCALE_FACTOR = 2;
    /** 收缩比例, 即实际利用率小于该值，收缩 arr 的空间, 已减少内存占用 */
    private static final double SHRINK_RATIO = 0.4;

    /** 成员变量 */
    private int[] arr;
    /** 当前可存放的位置 */
    private int currIndex;
    /** 记录上一次扩容的容量，便于缩容 */
    private int lastSize;

    public List(){
        arr = new int[DEFAULT_CAPACITY];
        currIndex = 0;
        lastSize = DEFAULT_CAPACITY;
    }

    public List(int size){
        arr = new int[size];
        currIndex = 0;
        lastSize = size;
    }

    @Override
    public int getSize() {
        return currIndex;
    }

    @Override
    public boolean isEmpty() {
        return currIndex == 0;
    }

    @Override
    public boolean isContain(int number) {
        for (int i = 0; i < currIndex; i++) {
            if (number == arr[i]){
                return true;
            }
        }
        return false;
    }

    @Override
    public int[] toArray() {
        return copyArray(arr, currIndex, 0, currIndex);
    }

    @Override
    public void clear() {
        currIndex = 0;
        // 全部清除，当然其实也可以不清除的
        for (int i = 0; i < arr.length; i++) {
            arr[i] = 0;
        }
    }

    @Override
    public String toStr() {
        String s = "";
        for (int i = 0; i < currIndex; i++) {
            s += arr[i] + " ";
        }
        // 返回s，并且去掉尾空格
        return s.trim();
    }

    @Override
    public void add(int number) {
        add(currIndex, number);
    }

    @Override
    public void add(int index, int number) {
        if (currIndex>=arr.length){
            scaleSize();
        }
        for (int i =currIndex; i > index; i--) {
            arr[i] = arr[i-1];
        }
        arr[index] = number;
        currIndex++;
    }

    @Override
    public void addFirst(int number) {
        this.add(0, number);
    }

    @Override
    public void remove() {
        remove(currIndex-1);
    }

    @Override
    public void removeFirst() {
        remove(0);
    }

    @Override
    public void remove(int index) {
        if (index >= currIndex || this.isEmpty()){
            return;
        }
        if (currIndex-1 == index){
            currIndex--;
            return;
        }
        for (int i = index; i < currIndex; i++) {
            arr[i] = arr[i+1];
        }
        currIndex--;
        shrink();
    }

    @Override
    public int get(int index) {
        rangeCheck(index);
        return arr[index];
    }

    @Override
    public int getFirst() {
        return get(0);
    }

    @Override
    public int get() {
        return get(currIndex-1);
    }

    /**
     * 扩容
     */
    private void scaleSize() {
        arr = copyArray(arr, SCALE_FACTOR* arr.length, 0, currIndex);
    }

    /**
     * 缩容
     */
    private void shrink(){
        if ((currIndex/arr.length)*1.0 <= SHRINK_RATIO){
            return;
        }
        // 上一次扩容的大小，等于当前数组大小，说明还没有扩容过
        if (lastSize == arr.length){
            return;
        }
        arr = copyArray(arr, lastSize, 0, currIndex);
    }

    /**
     * 判断输入的index的合法性
     * @param index
     */
    private void rangeCheck(int index){
        if (index > currIndex){
            throw new IndexOutOfBoundsException("outOfBounds " + index);
        }
    }

    /**
     * 写这个函数的目的，是由于前面我们写的method中，很多都需要数组迁移的功能
     * 为了减少重复代码，可以实现一个公共的方法
     * 静态的拷贝数组的函数,类似于java内置的 Arrays.copyOf() 函数
     * 这里我们用已学到的知识，自己去实现一下这个函数
     * 当然，这只是为了学习
     * 在实际的编程中，如果系统已经有了对应的功能，能调系统api的，尽量使用系统的
     * @param srcArr 原始数组
     * @param size  新数组大小
     * @param start 拷贝开始位置 前闭
     * @param end 结束位置  后开
     * @return  新数组
     */
    public static int[] copyArray(int[] srcArr,int size,  int start, int end){
        if (srcArr.length < end || start < 0){
            throw new IndexOutOfBoundsException("outOfBounds");
        }
        int[] newArr = new int[size];
        for (int i = start; i < end; i++) {
            newArr[i] = srcArr[i];
        }
        return newArr;
    }

}
